package org.midy.infrastructure.customer;

import org.midy.infrastructure.DefaultInformationDistribution;
import org.midy.infrastructure.IOEventDrivenWorker;
import org.midy.infrastructure.config.SysConfig;

import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class OnlineList {
    /* 账号 映射 网络连接映射列表 */
    private static final Map<String, UserLogin> ACCT_MAP_SOCKET = new ConcurrentHashMap<>();
    /* 网络 连接 账号映射列表 */
    private static final Map<SelectableChannel, UserLogin> SOCKET_MAP_ACCT = new ConcurrentHashMap<>();

    public static boolean registerOnline(String acct, SelectableChannel socketChannel, SelectionKey selectionKey, IOEventDrivenWorker worker) {
        UserLogin userLogin = new UserLogin(acct, socketChannel, selectionKey, worker);
        ACCT_MAP_SOCKET.put(acct, userLogin);
        SOCKET_MAP_ACCT.put(socketChannel, userLogin);
        // 由服务端进行：上线通知
        if (SysConfig.modeServer) {
            broadcastMessage(("系统通知： 欢迎【"+ acct +"】上线啦").getBytes(DefaultInformationDistribution.UTF8));
        }
        return true;
    }

    public static void logout(SelectableChannel selectableChannel) {
        UserLogin userLogin = SOCKET_MAP_ACCT.get(selectableChannel);
        if(userLogin != null) {
            SOCKET_MAP_ACCT.remove(selectableChannel);
            ACCT_MAP_SOCKET.remove(userLogin.acct);
            if (SysConfig.modeServer) {
                broadcastMessage(("系统通知： 【"+ userLogin.getAcct() +"】下线啦").getBytes(DefaultInformationDistribution.UTF8));
            }
        }
    }

    public static String broadcastMessage(byte[] message) {
        Set<String> acctSet = ACCT_MAP_SOCKET.keySet();
        for(String acct : acctSet) {
            UserLogin userLogin = ACCT_MAP_SOCKET.get(acct);
            userLogin.worker.register(userLogin.socketChannel, userLogin.selectionKey,SelectionKey.OP_WRITE, message);
        }
        return null;
    }

    public static boolean sendMessage(String acct, byte[] message) {
        UserLogin userLogin = ACCT_MAP_SOCKET.get(acct);
        if(Objects.nonNull(userLogin)) {
            userLogin.worker.register(userLogin.socketChannel, userLogin.selectionKey,SelectionKey.OP_WRITE, message);
            return true;
        }
        return false;
    }

    public static UserLogin query(SocketChannel socketChannel) {
        if(Objects.isNull(socketChannel)) {
            return null;
        } else {
            return SOCKET_MAP_ACCT.get(socketChannel);
        }
    }

    public static class UserLogin {
        public String acct;
        public SelectableChannel socketChannel;
        public SelectionKey selectionKey;
        public IOEventDrivenWorker worker;

        public UserLogin(String acct, SelectableChannel socketChannel, SelectionKey selectionKey, IOEventDrivenWorker worker) {
            this.acct = acct;
            this.socketChannel = socketChannel;
            this.selectionKey = selectionKey;
            this.worker = worker;
        }

        public UserLogin() {
        }

        public String getAcct() {
            return acct;
        }

        public SelectableChannel getSocketChannel() {
            return socketChannel;
        }

        public SelectionKey getSelectionKey() {
            return selectionKey;
        }

        public IOEventDrivenWorker getWorker() {
            return worker;
        }
    }


}
